const jwt = require("jsonwebtoken");

const errorTypes = require("../constans/error-types");
const authService = require("../service/auth.service");
const md5password = require("../utils/password-handle");
const { PUBLIC_KEY } = require("../app/config");
const User = require("../model/user.model");
const Apply = require("../model/apply.model");
const { logger } = require("../../logger");

const verifyLogin = async (ctx, next) => {
  ctx.verifyParams({
    username: { type: "string", required: true },
    password: { type: "string", required: true },
  });
  try {
    const { username, password } = ctx.request.body;

    // 判断用户是否存在
    const result = await User.findOne({
      where: { username },
      raw: true, // 设置为 true，即可返回源数据
    });
    if (!result) {
      return ctx.fail(400, "用户不存在");
    }

    // 判断密码是否一致（加密）传入的密码必须是字符串形式
    if (md5password(password) !== result.password) {
      const error = new Error(errorTypes.PASSWORD_IS_INCORRENT);
      return ctx.app.emit("error", error, ctx);
    }

    // 使用ctx获取到user
    ctx.user = result;
    await next();
  } catch (error) {
    logger.error(error);
    console.log(error);
  }
};

const verifyAuth = async (ctx, next) => {
  // 1.获取token
  const authorization = ctx.headers.authorization;
  if (!authorization) {
    const error = new Error(errorTypes.UNAUTHORIZATION);
    return ctx.app.emit("error", error, ctx);
  }
  // 这里的'Bearer '是有空格的
  const token = authorization.replace("Bearer ", "");
  // 2.验证token（id/name/iat/exp）
  try {
    const result = jwt.verify(token, PUBLIC_KEY, {
      algorithms: ["RS256"], // 采用的算法
    });
    ctx.user = result;
    await next();
  } catch (err) {
    if (err.name === "TokenExpiredError" || err.name === "JsonWebTokenError") {
      const error = new Error(errorTypes.UNAUTHORIZATION);
      ctx.app.emit("error", error, ctx);
    }
  }
};

// 验证管理员权限
const verifyAdminPermission = async (ctx, next) => {
  try {
    const authorization = ctx.headers.authorization;
    const token = authorization.replace("Bearer ", "");
    const result = jwt.verify(token, PUBLIC_KEY, {
      algorithms: ["RS256"], // 采用的算法
    });
    const { permission } = result;
    // 3是管理员权限
    if (permission !== 3) {
      const error = new Error(errorTypes.UNPERMISSION);
      return ctx.app.emit("error", error, ctx);
    }
    await next();
  } catch (error) {
    console.log(error);
    logger.error(error);
  }
};

/**
 * 1.很多的内容都需要验证权限：修改/删除动态，修改/删除评论
 * 2.接口：业务接口系统/后台管理系统
 * 一对一：user -> role
 * 多对多：role -> menu（删除动态/修改动态）
 */

// 第二种符合RESTful风格的方法
const verifyPermission = async (ctx, next) => {
  // 1.获取参数 {commentId ：'1'}
  const [resourceKey] = Object.keys(ctx.params);
  const tableName = resourceKey.replace("Id", "");
  const resourceId = ctx.params[resourceKey];
  const { id } = ctx.user;

  // 2.查询是否具备权限
  try {
    const isPermission = await authService.checkResource(
      tableName,
      resourceId,
      id
    );
    if (!isPermission) throw new Error();
    await next();
  } catch (err) {
    const error = new Error(errorTypes.UNPERMISSION);
    return ctx.app.emit("error", error, ctx);
  }
};

// 第一种解决方法
// 写了闭包,变成函数
// const verifyPermission = (tableName) => {
//     return async (ctx, next) => {
//         console.log("验证删除权限的middleware");

//         // 1.获取参数
//         const { momentId } = ctx.params
//         const { id } = ctx.user

//         // 2.查询是否具备权限
//         try {
//             const isPermission = await authService.checkResource(tableName, momentId, id)
//             if (!isPermission) throw new Error()
//             await next()
//         } catch (err) {
//             const error = new Error(errorTypes.UNPERMISSION)
//             return ctx.app.emit('error', error, ctx)
//         }
//     }
// }

module.exports = {
  verifyLogin,
  verifyAuth,
  verifyAdminPermission,
  verifyPermission,
};
